﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using MOJsdk;
using System.Windows.Threading;
using System.Threading;
using System.Collections.ObjectModel;
using IO = System.IO;

namespace MOJ.Control.MultiViewUserControl
{
    /// <summary>
    /// Interaction logic for Control_ViewMovies.xaml
    /// </summary>
    public partial class Control_ViewMovies : UserControl
    {
        private ObservableCollection<MOJMovie> _movies = null;
        private ObservableCollection<MOJMovie> _view = null;
        private MojMovieOrders _OrderBy;
        private MOJFilterPool _FiltersPool;
        private IHost _TheHost = null;
        private bool _loading = false;

        public Control_ViewMovies()
        {
            InitializeComponent();
            INI();
        }

        #region Inicialization
        private void INI()
        {
            _TheHost = GlobalVars.TheHost;
            _FiltersPool = new MOJFilterPool();
            _movies = new ObservableCollection<MOJMovie>();
            _view = new ObservableCollection<MOJMovie>();

            INIStyles();
            INIEvents();
            INIContextMenu();
        }
        private void INIEvents()
        {
            this.Loaded += OnLoaded;

            _listView.SelectionChanged += ListViewSelectionChanged;
        }
        private void INIStyles()
        {
            _rect.ApplyStyle("0101055");
            _image.ApplyStyle("0101056");
            _ForeGround_Grid.ApplyStyle("0101120");
            _ProgBar.ApplyStyle("0101121");
            _txt_progress.ApplyStyle("0101122");
            _Grid.ApplyStyle("0101123");
            _listView.ApplyStyle("0101057");
        }
        private void INIContextMenu()
        {
            ContextMenu menu = new ContextMenu();

            MenuItem play = new MenuItem();
            play.Header = MOJLocalization.Localize("Play");
            play.Click += ClickPlay;
            menu.Items.Add(play);

            MenuItem find = new MenuItem();
            find.Header = MOJLocalization.Localize("Show in Explorer");
            find.Click += ClickShowInExplorer;
            menu.Items.Add(find);

            MenuItem details = new MenuItem();
            details.Header = MOJLocalization.Localize("Details");
            details.Click += ClickShowMovieDetails;
            menu.Items.Add(details);

            _listView.ContextMenu = menu;
        }
        #endregion

        #region LoadData
        public void OnLoaded(object sender, RoutedEventArgs e)
        {
            if (_movies != null && _movies.Count > 0)
                return;

            LoadMovies();
        }

        public void LoadMovies()
        {
            NoArgs th = new NoArgs(LoadMoviesAsync);
            th.BeginInvoke(null, null);
        }
        private void LoadMoviesAsync()
        {
            if (_loading)
                return;

            _loading = true;
            _OrderBy = MojMovieOrders.MovieTitle;

            try
            {
                DispatcherOperation op;

                op = this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
                {
                    _ForeGround_Grid.Visibility = System.Windows.Visibility.Visible;
                });
                while (op.Status == DispatcherOperationStatus.Executing) { }

                _movies.Clear();
                List<string> list = new List<string>(GlobalVars.TheHost.LoadMoviesCodes());

                foreach (var v in list)
                {
                    _movies.Add(new MOJMovie(v));
                    op = this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
                    {
                        SetProgress(_movies.Count, list.Count);
                    });
                    while (op.Status == DispatcherOperationStatus.Executing) { }
                }

                op = this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
                {
                    _ForeGround_Grid.Visibility = System.Windows.Visibility.Hidden;
                });
                while (op.Status == DispatcherOperationStatus.Executing) { }

                _loading = false;
                _movies = new ObservableCollection<MOJMovie>(_movies.OrderBy(m => m.MovieTitle));
                BringDataIntoView(_movies);
            }
            catch(Exception ex)
            {
                GlobalVars.TheHost.ReportError(new ErrorReporter()
                {
                    ErrorCode = "Control_ViewMovies(LoadMoviesAsync)",
                    ErrorMessage = "Error loading movies",
                    ErrorDetails = ex.ToString(),
                });
            }

            _loading = false;
        }
        private void BringDataIntoView(IEnumerable<MOJMovie> LIST)
        {
            OneArg th = new OneArg(BringDataAsync);
            th.BeginInvoke(LIST, null, null);
        }
        private void BringDataAsync(object arg)
        {
            if (_loading)
                return;
            _loading = true;

            List<MOJMovie> list = new List<MOJMovie>(arg as IEnumerable<MOJMovie>);

            try
            {
                DispatcherOperation op;

                op = this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
                {
                    _ForeGround_Grid.Visibility = System.Windows.Visibility.Visible;
                    _listView.ItemsSource = null;
                    _view.Clear();
                    _listView.ItemsSource = _view;
                });
                while (op.Status == DispatcherOperationStatus.Executing) { }

                foreach (var v in list)
                {
                    op = this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
                    {
                        _view.Add(v);
                        SetProgress(_view.Count, list.Count);
                    });
                    while (op.Status == DispatcherOperationStatus.Executing) { }
                }

                op = this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate
                {
                    _ForeGround_Grid.Visibility = System.Windows.Visibility.Hidden;
                    GlobalVars.TheHost.AddToasts(string.Format("{0} Movies loaded", _view.Count));
                });
                while (op.Status == DispatcherOperationStatus.Executing) { }
            }
            catch (Exception ex)
            {
                GlobalVars.TheHost.ReportError(new ErrorReporter()
                {
                    ErrorCode = "Control_ViewMovies(BringDataAsync)",
                    ErrorMessage = "Error loading data into view",
                    ErrorDetails = ex.ToString(),
                });
            }
            _loading = false;
        }
        #endregion

        #region Events
        private void ListViewSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            int x = _listView.SelectedIndex;
            if (x == -1)
            {
                _TheHost.sv_SelectedMovie = "NULL";
            }
            else
            {
                _TheHost.sv_SelectedMovie = _view[x].MovieCode;
            }
        }
        private void ClickShowMovieDetails(object sender, RoutedEventArgs e)
        {
            int x = _listView.SelectedIndex;
            if (x == -1) return;

            GlobalVars.TheHost.ShowMovieDetails(_view[x].MovieCode);
        }
        private void ClickShowInExplorer(object sender, RoutedEventArgs e)
        {
            try
            {
                int x = _listView.SelectedIndex;
                if (x == -1) return;

                if (_view[x].MovieFiles.Count <= 0)
                    return;

                MOJBasicFileClass file = _view[x].MovieFiles[0];
                string path = file.FileFullPath;

                if (IO.File.Exists(path))
                {
                    string folder = IO.Path.GetDirectoryName(path);
                    string argument = string.Format("\"{0}\"", folder);
                    System.Diagnostics.Process.Start("explorer.exe", argument);
                }
            }
            catch
            {
                return;
            }
        }
        private void ClickPlay(object sender, RoutedEventArgs e)
        {
            try
            {
                int x = _listView.SelectedIndex;
                if (x == -1) return;

                if (_view[x].MovieFiles.Count <= 0)
                    return;

                MOJBasicFileClass file = _view[x].MovieFiles[0];

                if(file.IsAvaible)
                    GlobalVars.TheHost.PlayFile(file.FileFullPath);
            }
            catch
            {
                return;
            }
        }
        #endregion

        #region Filter
        public void SetOrder(MojMovieOrders order)
        {
            switch (order)
            {
                case MojMovieOrders.MovieTitle:
                    BringDataIntoView(_view.OrderBy(x => x.MovieTitle));
                    break;

                case MojMovieOrders.MovieDirectors:
                    BringDataIntoView(_view.OrderBy(x => x.MovieDirectors));
                    break;

                case MojMovieOrders.MovieGenres:
                    BringDataIntoView(_view.OrderBy(x => x.MovieGenres));
                    break;

                case MojMovieOrders.MovieWriters:
                    BringDataIntoView(_view.OrderBy(x => x.MovieWriters));
                    break;

                case MojMovieOrders.MovieYear:
                    BringDataIntoView(_view.OrderBy(x => x.MovieYear));
                    break;

                case MojMovieOrders.InMovieTitle:
                    BringDataIntoView(_view.OrderByDescending(x => x.MovieTitle));
                    break;

                case MojMovieOrders.InMovieDirectors:
                    BringDataIntoView(_view.OrderByDescending(x => x.MovieDirectors));
                    break;

                case MojMovieOrders.InMovieGenres:
                    BringDataIntoView(_view.OrderByDescending(x => x.MovieGenres));
                    break;

                case MojMovieOrders.InMovieWriters:
                    BringDataIntoView(_view.OrderByDescending(x => x.MovieWriters));
                    break;

                case MojMovieOrders.InMovieYear:
                    BringDataIntoView(_view.OrderByDescending(x => x.MovieYear));
                    break;

                default:
                    order = _OrderBy;
                    break;
            }

            _OrderBy = order;
        }
        public void ApplyFilters()
        {
            BringDataIntoView(_movies.Where(e => e.TestPool(_FiltersPool)));
            SetOrder(_OrderBy);
        }
        private void SetProgress(int value, int max)
        {
            _ProgBar.Maximum = max;
            _ProgBar.Value = value;
        }
        #endregion

        private delegate void NoArgs();
        private delegate void OneArg(object arg1);
    }
}
